CloudFormation Template for VPC with EC2 and ALB
Introduction
This CloudFormation Template creates a VPC with a private and a public subnet in each AZ. Each public subnet contains a EC2 Instance, which is connected to Application Load Balancer. VPC has an Internet Gateway and route tables for public and private subnets. The below image shows the architectural design of the template.
CloudFormation Template
The template code is written in YAML, where all the required resources are defined in Resources section and dynamic inputs in Parameters section.
--- Parameters: SecurityGroupDescription: Description: Security Group Description Type: String KeyName: Description: Key Pair for EC2 Type: 'AWS::EC2::KeyPair::KeyName' Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: VPC1 InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: VPC Internet Gateway AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway PublicSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 AvailabilityZone: us-east-2a MapPublicIpOnLaunch: true Tags: - Key: Name Value: Public Subnet 1 PrivateSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.2.0/24 MapPublicIpOnLaunch: false AvailabilityZone: us-east-2a Tags: - Key: Name Value: Private Subnet 1 PublicSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.3.0/24 AvailabilityZone: us-east-2b MapPublicIpOnLaunch: true Tags: - Key: Name Value: Public Subnet 2 PrivateSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.4.0/24 AvailabilityZone: us-east-2b MapPublicIpOnLaunch: false Tags: - Key: Name Value: Private Subnet 2 PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Public Route Table PublicRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnetRouteTableAssociation1: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable PublicSubnetRouteTableAssociation2: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicRouteTable PrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: Private Route Table PrivateSubnetRouteTableAssociation1: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1 RouteTableId: !Ref PrivateRouteTable PrivateSubnetRouteTableAssociation2: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet2 RouteTableId: !Ref PrivateRouteTable #EC2 Instances EC2Instance1: Type: AWS::EC2::Instance Properties: ImageId: ami-0233c2d874b811deb InstanceType: t2.micro SecurityGroupIds: - !Ref EC2SecurityGroup SubnetId: !Ref PublicSubnet1 KeyName: !Ref KeyName UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd #echo "<h1>Hello from Region us-east-2b</h1>" > /var/www/html/index.html Type: AWS::EC2::Instance Properties: ImageId: ami-0233c2d874b811deb InstanceType: t2.micro SecurityGroupIds: - !Ref EC2SecurityGroup SubnetId: !Ref PublicSubnet2 KeyName: !Ref KeyName UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd #echo "<h1>Hello from Region us-east-2b</h1>" > /var/www/html/index.html # EC2 and ALB Security Groups ELBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ELB Security Group VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 EC2SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Ref SecurityGroupDescription VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: Fn::GetAtt: - ELBSecurityGroup - GroupId - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: xxx.xxx.xxx.xxx # Target Group, Listener and Application Load Balancer EC2TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 15 HealthyThresholdCount: 5 Matcher: HttpCode: '200' Name: EC2TargetGroup Port: 80 Protocol: HTTP TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: '20' Targets: - Id: !Ref EC2Instance1 Port: 80 - Id: !Ref EC2Instance2 Port: 80 UnhealthyThresholdCount: 3 VpcId: !Ref VPC ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref EC2TargetGroup LoadBalancerArn: !Ref ApplicationLoadBalancer Port: 80 Protocol: HTTP ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 SecurityGroups: - !GetAtt ELBSecurityGroup.GroupId
Description of Resources Created
VPC
- VPC
- VPC is defined with CidrBlock 10.0.0.0/16.
- DnsHostnames is set to 'true' to get public DNS hostname.
- Subnets : a private and a public subnet is defined in each Availability Zone.
- Public Subnet 1 - in Availability Zone 1 with CidrBlock 10.0.1.0/24.
- Public Subnet 2 - in Availability Zone 2 with CidrBlock 10.0.3.0/24.
- Private Subnet 1 - in Availability Zone 1 with CidrBlock 10.0.2.0/24.
- Private Subnet 2 - in Availability Zone 2 with CidrBlock 10.0.4.0/24.
- Internet Gateway
- It provides a target for internet-routable traffic in your route tables.
- Route tables refer Internet Gateway as target for Destination.
- Route Tables
- Public Route Table : routes traffic either to Internet Gateway for outbounds or within 10.0.0.0/16. Public subnets in two Availability Zones are associated with the public route table.
-
- Private Route Table : routes traffic only within 10.0.0.0/16. Private subnets are associated with private route table.
EC2
- EC2 Instances
- Two EC2 Instances are defined in public subnet with user data to install Apache web server.
- The Instances have a reference to EC2 Security group and KeyPair.
- Security Groups:
- EC2 Security Group : Port 22 for SSH and Port 80 open to the Load Balancer.
-
- ELB Security Group : Port 80 open to everyone.
- Application Load Balancer : Load balancer is defined with Listener, target group and references ELB security group.
- Listener : The Listener is set with port 80 and protocol HTTP. The Listener forwards the traffic to targets in target group.
-
- Target Group : One target group is defined with two EC2 Instances as targets. Health Check port is set to 80.
Deploying CloudFormation Template
- Click on 'Create stack' in CloudFormation console. Choose 'Template is ready' and Specify the Template either through S3 URL or by directly uploading file. Click next to proceed further.
- Enter a name for stack to association with the resources created. Choose a keypair and enter a description for Security Group in the Parameters Section. Continue choosing next and click on 'Create Stack' .
- Creating Stack may take several minutes to launch all the resources with their dependencies. Deleting a Stack deletes all the resources associated with the stack.
Template Design
This is the template design automatically generated by CloudFormation based on the YAML file. This Design shows the defined resources and their dependencies.
Summary
We have successfully created VPC with EC2 Instances and Application Load Balancer using CloudFormation Template. CloudFormation is an easy way to create required resources and manage them in an orderly and easy manner. CloudFormation is a great way to represent architecture as code in your repository, which can be reused and controlled.